/**
 * 服务
 * */
package org.zmhhxl.sample3.oauth2.a.service;

import lombok.RequiredArgsConstructor;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.zmhhxl.sample3.oauth2.a.authentications.model.CustomOAuth2User;
import org.zmhhxl.sample3.oauth2.a.authentications.model.CustomOidcUser;
import org.zmhhxl.sample3.oauth2.a.authentications.strategy.context.Oauth2UserConverterContext;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

//@Service
//public class CustomOidcUserInfoService implements UserService<HttpRequest, OidcUser> {
//
//   private final OAuth2UserService<OidcUserRequest, OidcUser> delegate;
//
//   public CustomOidcUserInfoService(OAuth2UserService<OidcUserRequest, OidcUser> delegate) {
//      this.delegate = delegate;
//   }
//
//   @Override
//   public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
//      OidcUser oidcUser = delegate.loadUser(userRequest);
//
//      // 假设从数据库或其他服务获取额外信息
//      Map<String, Object> additionalInfo = fetchAdditionalUserInfo(oidcUser.getName());
//
//      // 创建一个新的OidcUserInfo对象，包含原始和额外的信息
//      OidcUserInfo extendedUserInfo = new OidcUserInfo(additionalInfo);
//
//      // 使用原始的ID Token和新增的UserInfo创建一个新的OidcUser实例
//      return new DefaultOidcUser(oidcUser.getAuthorities(), oidcUser.getIdToken(), extendedUserInfo);
//   }
//
//   private Map<String, Object> fetchAdditionalUserInfo(String username) {
//      // 实现此方法以从数据库或其他服务获取用户额外信息
//      // 这只是一个示例，实际实现应根据您的数据源进行调整
//      return Map.of("custom_attribute", "custom_value");
//   }
//}

@Service
/**
 * 自定义三方oidc登录用户信息服务
 * 无论两种调用都要使用此信息,作为userinfo
 * 适用于在处理 OpenID Connect 用户信息请求时，需要自定义和扩展用户信息的场景
 * */
@RequiredArgsConstructor
//@Component              //org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
public class CustomOidcUserInfoService extends OidcUserService {   //OidcUserService是客户端类型的UserService

 //private final UserInfoRepository userInfoRepository = new UserInfoRepository();

   private final IOauth2ThirdAccountService thirdAccountService;

   private final Oauth2UserConverterContext userConverterContext;

//OidcUserInfo

///public OidcUserInfo loadUser(String username){
//Map<String, Object> claims = this.userInfoRepository.findByUsername(username);
//   if (claims == null) {
//      throw new UsernameNotFoundException("User not found");
//   }
//  return new OidcUserInfo(claims);
// }

   @Override
   public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
      // 获取三方用户信息
      OidcUser oidcUser = super.loadUser(userRequest);
      // 转为项目中的三方用户信息
      CustomOAuth2User basicOauth2User = userConverterContext.convert(userRequest, oidcUser);
      // 检查用户信息,在后面登录成功的地方处理保存
      //thirdAccountService.checkAndSaveUser(basicOauth2User);

      // 重新生成oidcUser
      if (StringUtils.hasText(basicOauth2User.getNameAttributeKey())) {
         return new CustomOidcUser(oidcUser, oidcUser.getIdToken(), oidcUser.getUserInfo(), basicOauth2User.getNameAttributeKey());
      }
      return new CustomOidcUser(oidcUser, oidcUser.getIdToken(), oidcUser.getUserInfo());

}

static class UserInfoRepository {

   private final Map<String, Map<String, Object>> userInfo = new HashMap<>();

   public UserInfoRepository() {
      this.userInfo.put("user1", createUser("user1"));
      this.userInfo.put("user2", createUser("user2"));
      //确认用户信息是从Github获取并转换为Spring Security所需的UserDetails对象
      this.userInfo.put("zmhhxl1", createUser("zmhhxl1"));
      //确认用户信息是否能正确地从Gitee获取并转换为Spring Security所需的UserDetails对象
      this.userInfo.put("user_7692374", createUser("user_7692374"));
   }

   public Map<String, Object> findByUsername(String username) {
      return this.userInfo.get(username);
   }

   private static Map<String, Object> createUser(String username) {
      return OidcUserInfo.builder()
            .subject(username)
            .name("First Last")
            .givenName("First")
            .familyName("Last")
            .middleName("Middle")
            .nickname("User")
            .preferredUsername(username)
            .profile("https://example.com/" + username)
            .picture("https://example.com/" + username + ".jpg")
            .website("https://example.com")
            .email(username + "@example.com")
            .emailVerified(true)
            .gender("female")
            .birthdate("1970-01-01")
            .zoneinfo("Europe/Paris")
            .locale("en-US")
            .phoneNumber("+1 (604) 555-1234;ext=5678")
            .phoneNumberVerified(false)
            .claim("address", Collections.singletonMap("formatted", "Champ de Mars\n5 Av. Anatole France\n75007 Paris\nFrance"))
            .updatedAt("1970-01-01T00:00:00Z")
            .build()
            .getClaims();
   }
}

}

